#include "N1ProtoData.h"
#include "N1Lib.h"

#define N1PROTO_TYPE_SIZE       1
#define N1PROTO_SIZE_SIZE       4
#define N1PROTO_COUNT_SIZE      4

//TYPES 
#define N1PROTO_INT32           1
#define N1PROTO_ANSI_STRING     2
#define N1PROTO_UNICODE_STRING  3
#define N1PROTO_DATA            4
#define N1PROTO_ARRAY           5
#define N1PROTO_DICTIONARY      6
#define N1PROTO_INT64           7


/*****************************************************

-------------------
| 0x01 |  0x8304  |               // In little endian (Intel) byte order 
-------------------
--------------------------------
| 0x02 | Size | Ansi string    |
--------------------------------
--------------------------------
| 0x03 | Size | U n i c o d e  |  // In little endian (Intel) byte order 
--------------------------------
--------------------------------
| 0x04 | Size |     Data       |
--------------------------------
--------------------------------
| 0x05 | Count | Value | Value |
--------------------------------
-----------------------------------------------------
| 0x06 | Count of pairs | Key | Value | Key | Value |
-----------------------------------------------------

*****************************************************/

//TYPES 
#define N1PROTO_INT32           1
#define N1PROTO_ANSI_STRING     2
#define N1PROTO_UNICODE_STRING  3
#define N1PROTO_DATA            4
#define N1PROTO_ARRAY           5
#define N1PROTO_DICTIONARY      6
#define N1PROTO_INT64           7


/*****************************************************
     
All numbers and unicode strings in big endian (network) byte order

-------------------
| 0x01 |  0x8304  | 
-------------------
--------------------------------
| 0x02 | Size | Ansi string    |
--------------------------------
--------------------------------
| 0x03 | Size | U n i c o d e  |  
--------------------------------
--------------------------------
| 0x04 | Size |     Data       |
--------------------------------
--------------------------------
| 0x05 | Count | Value | Value |
--------------------------------
-----------------------------------------------------
| 0x06 | Count of pairs | Key | Value | Key | Value |
-----------------------------------------------------

*****************************************************/

N1NAME_DEF(N1ProtoData)

#define N1PROTO_MIN_SIZE  100

void N1ProtoData::allocSpace(uint32 bytes)
{
    uint32 allocatedSize = size();
    uint32 freeSize = allocatedSize - m_nDataSize;

    if(freeSize < bytes) //need to realloc
    {
        setSize( N1GetNewSizeByLog2(allocatedSize, bytes, N1PROTO_MIN_SIZE) );
    }
}

void N1ProtoData::addMemory(const void* ptr, uint32 size)
{
    allocSpace(size);
    memcpy((char*)bytes() + m_nDataSize, ptr, size );
    m_nDataSize += size;
}

void N1ProtoData::addByte(uint8 b)
{
    addMemory(&b, sizeof(b));
}

void N1ProtoData::addShort(uint16 s)
{
    s = N1H2N16(s);
    addMemory(&s, sizeof(s));
}

void N1ProtoData::addInt(uint32 i)
{
    i = N1H2N32(i);
    addMemory(&i, sizeof(i));
}

void N1ProtoData::addNumber(const N1Number *n)
{
    uint32 intSize = n->size();
    
    allocSpace( N1PROTO_TYPE_SIZE + intSize);

    N1Assert(intSize==4);

    uint32 i = *n;

    addByte(N1PROTO_INT32);
    addInt(i);
}

void N1ProtoData::addString(pcstr str)
{
    uint32 len = strlen(str);

    allocSpace( N1PROTO_TYPE_SIZE + N1PROTO_SIZE_SIZE + len);

    addByte(N1PROTO_ANSI_STRING);
    addInt(len);
    addMemory(str, len);
}

void N1ProtoData::addString(pcwstr str)
{
    uint32 len = wcslen(str);

    allocSpace( N1PROTO_TYPE_SIZE + N1PROTO_SIZE_SIZE + len * sizeof(wchar_t));

    addByte(N1PROTO_UNICODE_STRING);
    addInt(len);
    addMemory(str, len * sizeof(wchar_t));
}

void N1ProtoData::addData(const void* ptr, uint32 size)
{
    allocSpace( N1PROTO_TYPE_SIZE + N1PROTO_SIZE_SIZE + size);
    addByte(N1PROTO_DATA);
    addInt(size);
    addMemory(ptr, size);
}

void N1ProtoData::addArray(const N1Array *array)
{
    uint32 i, count = array->count();
    for(i=0;i<count;i++)
    {

    }
}

void N1ProtoData::addDictionary(const N1Dictionary *dict)
{
}
